import angular = require("angular");

interface Component{
    readonly componentKey: string;  // 组件标识
    readonly componentProps: ComponentProps;
    readonly  bridge: Bridge;
    init(bridge: Bridge):void;
}

interface ComponentProps{
    title: string;
    readonly componentKey: string;
}

interface ComponentArray{
     [index: number]: Component;
}

interface ComponentGroup extends Component{
    readonly children: ComponentArray;

    addComponent(component: Component): void;     // 追加组件

    setIndexComponent (number, Component): void; // 设置某个位置上的组件

    removeComponentIndex(index:number):void;

    removeComponent(component: Component):void;
}

class Bridge{
    private scope: angular.IScope;

    private $dom: JQLite;

    constructor(scope: angular.IScope, component: JQLite){
        this.scope = scope;
        this.$dom = component;
    }

    refresh():void{
        this.scope.$digest();
    }

    is(component: JQLite): boolean{
        return this.$dom.is(component);
    }

    getDom(): JQLite{
        return this.$dom;
    }
}

abstract class AbstractComponent implements Component{
    bridge: Bridge;
    componentKey: string;
    componentProps: ComponentProps;

    init(bridge: Bridge){
        this.bridge = bridge;
    }

}

abstract class AbstractGroup extends AbstractComponent implements  ComponentGroup{
    children: Array<Component>;

    abstract addComponent(component: Component): void;     // 追加组件

    abstract setIndexComponent (number, Component): void; // 设置某个位置上的组件

    abstract removeComponentIndex(index:number):void;

    abstract removeComponent(component: Component):void;
}

abstract class Layout extends  AbstractGroup{
    addComponent(component: Component): void{
        // this.children.push(component);
    }
    setIndexComponent(index: number, component: Component): void{
        if(index <0 || index >= this.children.length){
            throw new Error("out bound of children");
        }
        this.children[index] = component;
    }

    removeComponentIndex(index:number):void{

    }

    removeComponent(component: Component):void{
        component.bridge.getDom().remove();
    }
}

export {Component, ComponentProps, ComponentGroup, AbstractComponent, AbstractGroup, Layout, Bridge};
export default Component;